using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;
using TenantManagementService.Tenants;
using TenantManagementService.Monitoring;

namespace TenantManagementService.Monitoring
{
    /// <summary>
    /// 健康检查服务
    /// </summary>
    public class HealthCheckService : ITransientDependency
    {
        private readonly IRepository<Tenant, Guid> _tenantRepository;
        private readonly IRepository<AlertRule, Guid> _alertRuleRepository;
        private readonly IRepository<Alert, Guid> _alertRepository;
        private readonly PrometheusMetricsService _prometheusMetricsService;
        private readonly ILogger<HealthCheckService> _logger;

        public HealthCheckService(
            IRepository<Tenant, Guid> tenantRepository,
            IRepository<AlertRule, Guid> alertRuleRepository,
            IRepository<Alert, Guid> alertRepository,
            PrometheusMetricsService prometheusMetricsService,
            ILogger<HealthCheckService> logger)
        {
            _tenantRepository = tenantRepository;
            _alertRuleRepository = alertRuleRepository;
            _alertRepository = alertRepository;
            _prometheusMetricsService = prometheusMetricsService;
            _logger = logger;
        }

        /// <summary>
        /// 执行综合健康检查
        /// </summary>
        [UnitOfWork]
        public async Task<SystemHealthStatus> PerformComprehensiveHealthCheckAsync(CancellationToken cancellationToken = default)
        {
            var startTime = DateTime.UtcNow;
            var stopwatch = Stopwatch.StartNew();

            try
            {
                var healthStatus = new SystemHealthStatus
                {
                    OverallStatus = HealthStatus.Unknown,
                    ComponentStatus = new Dictionary<string, HealthStatus>(),
                    Metrics = new Dictionary<string, object>(),
                    LastCheckTime = startTime,
                    Issues = new List<string>()
                };

                // 检查各个组件
                await CheckDatabaseHealthAsync(healthStatus, cancellationToken);
                await CheckTenantManagementHealthAsync(healthStatus, cancellationToken);
                await CheckAlertSystemHealthAsync(healthStatus, cancellationToken);
                await CheckMetricsHealthAsync(healthStatus, cancellationToken);
                CheckSystemResourcesHealthAsync(healthStatus);
                CheckApplicationHealthAsync(healthStatus);

                // 计算总体健康状态
                healthStatus.OverallStatus = CalculateOverallHealthStatus(healthStatus.ComponentStatus);

                // 记录健康检查耗时
                stopwatch.Stop();
                healthStatus.Metrics["health_check_duration_ms"] = stopwatch.ElapsedMilliseconds;
                healthStatus.Metrics["health_check_timestamp"] = startTime;

                // 记录 Prometheus 指标
                RecordHealthCheckMetrics(healthStatus);

                _logger.LogInformation("综合健康检查完成 - 状态: {Status}, 耗时: {Duration}ms",
                    healthStatus.OverallStatus, stopwatch.ElapsedMilliseconds);

                return healthStatus;
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "综合健康检查失败，耗时: {Duration}ms", stopwatch.ElapsedMilliseconds);

                return new SystemHealthStatus
                {
                    OverallStatus = HealthStatus.Unhealthy,
                    ComponentStatus = new Dictionary<string, HealthStatus>(),
                    Metrics = new Dictionary<string, object>
                    {
                        ["health_check_duration_ms"] = stopwatch.ElapsedMilliseconds,
                        ["health_check_timestamp"] = startTime
                    },
                    LastCheckTime = startTime,
                    Issues = new List<string> { $"健康检查异常: {ex.Message}" }
                };
            }
        }

        /// <summary>
        /// 检查数据库健康状态
        /// </summary>
        private async Task CheckDatabaseHealthAsync(SystemHealthStatus healthStatus, CancellationToken cancellationToken)
        {
            try
            {
                var startTime = DateTime.UtcNow;
                var stopwatch = Stopwatch.StartNew();

                // 尝试查询租户数据
                var tenantCount = await _tenantRepository.CountAsync(cancellationToken: cancellationToken);

                stopwatch.Stop();

                var status = tenantCount >= 0 ? HealthStatus.Healthy : HealthStatus.Unhealthy;
                healthStatus.ComponentStatus["database"] = status;

                healthStatus.Metrics["database_tenant_count"] = tenantCount;
                healthStatus.Metrics["database_query_duration_ms"] = stopwatch.ElapsedMilliseconds;

                if (status == HealthStatus.Unhealthy)
                {
                    healthStatus.Issues.Add("数据库连接异常，无法查询租户数据");
                }

                _logger.LogDebug("数据库健康检查完成 - 状态: {Status}, 租户数: {Count}, 查询耗时: {Duration}ms",
                    status, tenantCount, stopwatch.ElapsedMilliseconds);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["database"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"数据库健康检查失败: {ex.Message}");
                _logger.LogError(ex, "数据库健康检查失败");
            }
        }

        /// <summary>
        /// 检查租户管理健康状态
        /// </summary>
        private async Task CheckTenantManagementHealthAsync(SystemHealthStatus healthStatus, CancellationToken cancellationToken)
        {
            try
            {
                var tenants = await _tenantRepository.GetListAsync(cancellationToken: cancellationToken);
                var activeTenants = tenants.Count(t => t.IsEnabled && t.Status == TenantStatus.Active);
                var expiredTenants = tenants.Count(t => t.IsExpired());
                var suspendedTenants = tenants.Count(t => t.Status == TenantStatus.Suspended);

                healthStatus.ComponentStatus["tenant_management"] = HealthStatus.Healthy;

                healthStatus.Metrics["tenant_total_count"] = tenants.Count;
                healthStatus.Metrics["tenant_active_count"] = activeTenants;
                healthStatus.Metrics["tenant_expired_count"] = expiredTenants;
                healthStatus.Metrics["tenant_suspended_count"] = suspendedTenants;

                // 检查过期租户比例
                var expiredRatio = tenants.Count > 0 ? (double)expiredTenants / tenants.Count : 0;
                if (expiredRatio > 0.3) // 超过30%的租户过期
                {
                    healthStatus.ComponentStatus["tenant_management"] = HealthStatus.Warning;
                    healthStatus.Issues.Add($"过期租户比例较高: {expiredRatio:P1}");
                }

                _logger.LogDebug("租户管理健康检查完成 - 总计: {Total}, 活跃: {Active}, 过期: {Expired}",
                    tenants.Count, activeTenants, expiredTenants);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["tenant_management"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"租户管理健康检查失败: {ex.Message}");
                _logger.LogError(ex, "租户管理健康检查失败");
            }
        }

        /// <summary>
        /// 检查告警系统健康状态
        /// </summary>
        private async Task CheckAlertSystemHealthAsync(SystemHealthStatus healthStatus, CancellationToken cancellationToken)
        {
            try
            {
                var alertRules = await _alertRuleRepository.GetListAsync(cancellationToken: cancellationToken);
                var enabledAlertRules = alertRules.Count(r => r.IsEnabled);
                var activeAlerts = await _alertRepository.CountAsync(a => a.Status == AlertStatus.Active, cancellationToken: cancellationToken);

                healthStatus.ComponentStatus["alert_system"] = HealthStatus.Healthy;

                healthStatus.Metrics["alert_rules_total"] = alertRules.Count;
                healthStatus.Metrics["alert_rules_enabled"] = enabledAlertRules;
                healthStatus.Metrics["alerts_active_count"] = activeAlerts;

                // 检查活跃告警数量
                if (activeAlerts > 50)
                {
                    healthStatus.ComponentStatus["alert_system"] = HealthStatus.Warning;
                    healthStatus.Issues.Add($"活跃告警数量过多: {activeAlerts}");
                }
                else if (activeAlerts > 100)
                {
                    healthStatus.ComponentStatus["alert_system"] = HealthStatus.Unhealthy;
                    healthStatus.Issues.Add($"活跃告警数量异常: {activeAlerts}");
                }

                // 检查启用的告警规则数量
                if (enabledAlertRules == 0)
                {
                    healthStatus.ComponentStatus["alert_system"] = HealthStatus.Warning;
                    healthStatus.Issues.Add("没有启用的告警规则");
                }

                _logger.LogDebug("告警系统健康检查完成 - 规则: {Rules}, 活跃告警: {Alerts}",
                    enabledAlertRules, activeAlerts);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["alert_system"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"告警系统健康检查失败: {ex.Message}");
                _logger.LogError(ex, "告警系统健康检查失败");
            }
        }

        /// <summary>
        /// 检查指标系统健康状态
        /// </summary>
        private async Task CheckMetricsHealthAsync(SystemHealthStatus healthStatus, CancellationToken cancellationToken)
        {
            try
            {
                var prometheusStats = _prometheusMetricsService.GetStatistics();

                healthStatus.ComponentStatus["metrics_system"] = HealthStatus.Healthy;

                healthStatus.Metrics["metrics_total"] = prometheusStats.TotalMetrics;
                healthStatus.Metrics["metrics_counters"] = prometheusStats.Counters;
                healthStatus.Metrics["metrics_gauges"] = prometheusStats.Gauges;
                healthStatus.Metrics["metrics_histograms"] = prometheusStats.Histograms;
                healthStatus.Metrics["metrics_summaries"] = prometheusStats.Summaries;
                healthStatus.Metrics["metrics_last_updated"] = prometheusStats.LastUpdated;

                // 检查指标系统是否在正常更新
                var timeSinceLastUpdate = DateTime.UtcNow - prometheusStats.LastUpdated;
                if (timeSinceLastUpdate.TotalMinutes > 10) // 超过10分钟没有更新
                {
                    healthStatus.ComponentStatus["metrics_system"] = HealthStatus.Warning;
                    healthStatus.Issues.Add($"指标系统长时间未更新: {timeSinceLastUpdate.TotalMinutes:F1}分钟");
                }

                _logger.LogDebug("指标系统健康检查完成 - 总指标: {Total}, 最后更新: {LastUpdated}",
                    prometheusStats.TotalMetrics, prometheusStats.LastUpdated);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["metrics_system"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"指标系统健康检查失败: {ex.Message}");
                _logger.LogError(ex, "指标系统健康检查失败");
            }
        }

        /// <summary>
        /// 检查系统资源健康状态
        /// </summary>
        private void CheckSystemResourcesHealthAsync(SystemHealthStatus healthStatus)
        {
            try
            {
                var process = Process.GetCurrentProcess();
                var memoryUsageMB = process.WorkingSet64 / 1024 / 1024;
                var memoryUsagePercent = (double)process.WorkingSet64 / (process.PrivateMemorySize64 + 1) * 100;

                healthStatus.ComponentStatus["system_resources"] = HealthStatus.Healthy;

                healthStatus.Metrics["system_memory_usage_mb"] = memoryUsageMB;
                healthStatus.Metrics["system_memory_usage_percent"] = memoryUsagePercent;
                healthStatus.Metrics["system_gc_total_mb"] = GC.GetTotalMemory(false) / 1024 / 1024;
                healthStatus.Metrics["system_gc_gen0"] = GC.CollectionCount(0);
                healthStatus.Metrics["system_gc_gen1"] = GC.CollectionCount(1);
                healthStatus.Metrics["system_gc_gen2"] = GC.CollectionCount(2);
                healthStatus.Metrics["system_process_id"] = process.Id;
                healthStatus.Metrics["system_thread_count"] = process.Threads.Count;

                // 检查内存使用
                if (memoryUsageMB > 2048) // 超过2GB
                {
                    healthStatus.ComponentStatus["system_resources"] = HealthStatus.Warning;
                    healthStatus.Issues.Add($"内存使用较高: {memoryUsageMB}MB");
                }
                else if (memoryUsageMB > 4096) // 超过4GB
                {
                    healthStatus.ComponentStatus["system_resources"] = HealthStatus.Unhealthy;
                    healthStatus.Issues.Add($"内存使用过高: {memoryUsageMB}MB");
                }

                // 检查GC压力
                var totalCollections = GC.CollectionCount(0) + GC.CollectionCount(1) + GC.CollectionCount(2);
                healthStatus.Metrics["system_gc_total_collections"] = totalCollections;

                _logger.LogDebug("系统资源健康检查完成 - 内存: {MemoryMB}MB, GC次数: {GCCollections}",
                    memoryUsageMB, totalCollections);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["system_resources"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"系统资源健康检查失败: {ex.Message}");
                _logger.LogError(ex, "系统资源健康检查失败");
            }
        }

        /// <summary>
        /// 检查应用程序健康状态
        /// </summary>
        private void CheckApplicationHealthAsync(SystemHealthStatus healthStatus)
        {
            try
            {
                var uptime = DateTime.UtcNow - Process.GetCurrentProcess().StartTime;

                healthStatus.ComponentStatus["application"] = HealthStatus.Healthy;

                healthStatus.Metrics["application_uptime_seconds"] = uptime.TotalSeconds;
                healthStatus.Metrics["application_start_time"] = Process.GetCurrentProcess().StartTime;
                healthStatus.Metrics["application_version"] = typeof(HealthCheckService).Assembly.GetName().Version?.ToString() ?? "Unknown";
                healthStatus.Metrics["application_environment"] = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Unknown";
                healthStatus.Metrics["application_machine_name"] = Environment.MachineName;
                healthStatus.Metrics["application_os_version"] = Environment.OSVersion.ToString();

                // 检查应用程序启动时间（正常启动时间应该在合理范围内）
                if (uptime.TotalMinutes < 1)
                {
                    healthStatus.ComponentStatus["application"] = HealthStatus.Warning;
                    healthStatus.Issues.Add("应用程序刚刚启动，可能还在初始化");
                }

                _logger.LogDebug("应用程序健康检查完成 - 运行时间: {Uptime}, 版本: {Version}",
                    uptime, healthStatus.Metrics["application_version"]);
            }
            catch (Exception ex)
            {
                healthStatus.ComponentStatus["application"] = HealthStatus.Unhealthy;
                healthStatus.Issues.Add($"应用程序健康检查失败: {ex.Message}");
                _logger.LogError(ex, "应用程序健康检查失败");
            }
        }

        /// <summary>
        /// 计算总体健康状态
        /// </summary>
        private static HealthStatus CalculateOverallHealthStatus(Dictionary<string, HealthStatus> componentStatus)
        {
            if (!componentStatus.Any())
            {
                return HealthStatus.Unknown;
            }

            var statuses = componentStatus.Values.ToList();

            // 如果有任何组件不健康，则整体不健康
            if (statuses.Any(s => s == HealthStatus.Unhealthy))
            {
                return HealthStatus.Unhealthy;
            }

            // 如果有任何组件警告，则整体警告
            if (statuses.Any(s => s == HealthStatus.Warning))
            {
                return HealthStatus.Warning;
            }

            // 如果所有组件都健康，则整体健康
            if (statuses.All(s => s == HealthStatus.Healthy))
            {
                return HealthStatus.Healthy;
            }

            return HealthStatus.Unknown;
        }

        /// <summary>
        /// 记录健康检查指标到 Prometheus
        /// </summary>
        private void RecordHealthCheckMetrics(SystemHealthStatus healthStatus)
        {
            try
            {
                // 记录总体健康状态（1=健康, 2=警告, 3=不健康, 4=未知）
                var healthValue = healthStatus.OverallStatus switch
                {
                    HealthStatus.Healthy => 1,
                    HealthStatus.Warning => 2,
                    HealthStatus.Unhealthy => 3,
                    _ => 4
                };

                _prometheusMetricsService.RecordGauge("application_health_status", healthValue);

                // 记录组件状态
                foreach (var component in healthStatus.ComponentStatus)
                {
                    var componentValue = component.Value switch
                    {
                        HealthStatus.Healthy => 1,
                        HealthStatus.Warning => 2,
                        HealthStatus.Unhealthy => 3,
                        _ => 4
                    };

                    _prometheusMetricsService.RecordGauge(
                        "application_component_health_status",
                        componentValue,
                        new Dictionary<string, string> { ["component"] = component.Key });
                }

                // 记录问题数量
                _prometheusMetricsService.RecordGauge("application_health_issues_count", healthStatus.Issues.Count);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "记录健康检查指标到 Prometheus 失败");
            }
        }

        /// <summary>
        /// 获取简化的健康状态摘要
        /// </summary>
        public async Task<HealthSummary> GetHealthSummaryAsync(CancellationToken cancellationToken = default)
        {
            var healthStatus = await PerformComprehensiveHealthCheckAsync(cancellationToken);

            return new HealthSummary
            {
                OverallStatus = healthStatus.OverallStatus,
                ComponentCount = healthStatus.ComponentStatus.Count,
                HealthyComponents = healthStatus.ComponentStatus.Values.Count(s => s == HealthStatus.Healthy),
                WarningComponents = healthStatus.ComponentStatus.Values.Count(s => s == HealthStatus.Warning),
                UnhealthyComponents = healthStatus.ComponentStatus.Values.Count(s => s == HealthStatus.Unhealthy),
                IssueCount = healthStatus.Issues.Count,
                LastCheckTime = healthStatus.LastCheckTime,
                UptimeSeconds = healthStatus.Metrics.ContainsKey("application_uptime_seconds") ?
                    Convert.ToDouble(healthStatus.Metrics["application_uptime_seconds"]) : 0
            };
        }
    }

    /// <summary>
    /// 健康状态摘要
    /// </summary>
    public class HealthSummary
    {
        public HealthStatus OverallStatus { get; set; }
        public int ComponentCount { get; set; }
        public int HealthyComponents { get; set; }
        public int WarningComponents { get; set; }
        public int UnhealthyComponents { get; set; }
        public int IssueCount { get; set; }
        public DateTime LastCheckTime { get; set; }
        public double UptimeSeconds { get; set; }
    }
}